package logindbmanager

import (
	"src/dblink"
	"src/gcommon"
	"src/server/Login/symbol"
	"sync"

	"github.com/spf13/viper"
)

type LoginDBManager struct {
	mysqlConf *gcommon.MysqlConfig
	MysqlDB   *dblink.MysqlAccess

	lkGroupList sync.RWMutex
	// groupList   map[uint32]*protoMsg.GroupMD //服务器列表，从DB来的

	lkGlobalSrvList sync.RWMutex
	// GlobalSrvList   *login.GetGroupListAck //login服的全局缓存服务器列表

	lkWhiteList sync.RWMutex
	// whiteList   []*protoMsg.WhiteListMD
}

var inst *LoginDBManager

func GetInst() *LoginDBManager {
	if inst == nil {
		inst = &LoginDBManager{
			mysqlConf: gcommon.NewMysqlConfig(
				func(field string) string {
					return viper.GetString("Login." + field)
				}),
			// GlobalSrvList: new(login.GetGroupListAck),
			// groupList:     map[uint32]*protoMsg.GroupMD{},
		}
		inst.initManager()
	}
	return inst
}

func (this *LoginDBManager) initManager() {
	this.MysqlDB = dblink.NewMysqlAccess(
		dblink.SetMysqlAccessByConfig(this.mysqlConf),
	)
	// this.mysqlConf.UserName + this.mysqlConf.Address + this.mysqlConf.DBName
	symbol.LoginSalt = gcommon.GetCfgInst().Config.LoginSrvVerifyToken

	// this.AutoMigrate()
	// this.InitArea()
	// this.InitGroupDB()
}

// AutoMigrate 自动迁移表格
func (this *LoginDBManager) AutoMigrate() {
	// this.MysqlDB.AutoMigrate(&protoMsg.PlayerMD{})
	// this.MysqlDB.AutoMigrate(&protoMsg.UserMD{})
	// this.MysqlDB.AutoMigrate(&protoMsg.AreaMD{})
	// this.MysqlDB.AutoMigrate(&protoMsg.GroupMD{})
	// this.MysqlDB.AutoMigrate(&protoMsg.WhiteListMD{})
}

// GetSrvInfo 获取服务器编号
func (this *LoginDBManager) GetSrvInfo() string {
	return "1.0.0"
}

// // GetSrvRecommend 获取推荐服务器信息
// func (this *LoginDBManager) GetSrvRecommend(uid uint64) *login.GetSrvRecommendAck {
// 	sid := this.QueryRecommendGroupID(uid)
// 	if sid == 0 {
// 		logger.Warn("LoginDBManager GetSrvRecommend sid not fid uid: ", uid)
// 		return nil
// 	}
// 	smd := this.GetGroupMDByCache(sid)
// 	if smd == nil {
// 		logger.Warn("LoginDBManager GetSrvRecommend querySrvData not fid uid: ", uid)
// 		return nil
// 	}
// 	amd := this.queryAreaData(smd.AreaID)
// 	if amd == nil {
// 		logger.Warn("LoginDBManager GetSrvRecommend queryAreaData not fid uid: ", uid)
// 		return nil
// 	}
// 	ret := &login.GetSrvRecommendAck{
// 		AreaName: amd.AreaName,
// 		SrvName:  smd.GName,
// 		Uid:      uid,
// 		SrvID:    sid,
// 		SrvLoad:  int(smd.Load),
// 	}
// 	return ret
// }

// // 更新服务器缓存数据 正常是定时更新，如有服务器数量变化延迟1s更新（暂定）
// func (ldm *LoginDBManager) MakeCacheAllSrvList(tli map[uint32]*protoMsg.GroupMD) {

// 	amds := ldm.QueryAreaList()
// 	smds := []*protoMsg.GroupMD{}
// 	if tli != nil {
// 		for _, v := range tli {
// 			smds = append(smds, v)
// 		}
// 		sort.Slice(smds, func(i, j int) bool {
// 			return smds[i].GroupID < smds[j].GroupID
// 		})
// 	} else {
// 		smds = ldm.QueryGroupList()
// 	}
// 	gsrvli := new(login.GetGroupListAck)
// 	gsrvli.AreaList = make([]login.AreaInfo, len(amds)+1)

// 	//装载推荐服
// 	recomArea := new(login.AreaInfo)
// 	recomArea.AreaID = 0
// 	recomArea.AreaName = "Recommend"
// 	recomArea.GroupList = make([]*login.GroupInfo, 0)
// 	gsrvli.AreaList[0] = *recomArea
// 	var areaIdIndexMap = make(map[uint64]int)
// 	//大区 填入
// 	for index, amd := range amds {
// 		ai := new(login.AreaInfo)
// 		ai.AreaID = amd.AreaID
// 		ai.AreaName = amd.AreaName
// 		ai.GroupList = make([]*login.GroupInfo, 0)
// 		areaIdIndexMap[ai.AreaID] = 1 + index
// 		gsrvli.AreaList[areaIdIndexMap[ai.AreaID]] = *ai
// 	}
// 	//小区服填入 (推荐服自动填入推荐区 推荐标记后台数据库控制)
// 	for _, smd := range smds {
// 		if areaIdIndexMap[smd.AreaID] == 0 {
// 			continue
// 		}
// 		area := &gsrvli.AreaList[areaIdIndexMap[smd.AreaID]]
// 		gi := ToLoginGroupMsg(smd)
// 		_ = gi.SrvOpenTime //这里不过滤开服时间,获取Ack的时候 再过滤.
// 		area.GroupList = append(area.GroupList, gi)
// 		if gi.IsRecommend {
// 			gsrvli.AreaList[0].GroupList = append(gsrvli.AreaList[0].GroupList, gi)
// 		}
// 	}

// 	for _, aInfo := range gsrvli.AreaList {
// 		aInfo.SortGroup()
// 	}
// 	util.UsingWiter(&ldm.lkGlobalSrvList, func() {
// 		ldm.GlobalSrvList = gsrvli
// 	})
// }

// // 将groupMD 转为login的消息(字段会有些许不同,json字段名也有不一致)
// func ToLoginGroupMsg(smd *protoMsg.GroupMD) *login.GroupInfo {
// 	gi := new(login.GroupInfo)
// 	gi.UpdateFromMd(smd)
// 	gi.AreaID = 0

// 	//gi.GroupID = smd.GroupID
// 	//gi.SrvOpenTime = smd.SrvOpenTime //给客户端的GroupInfo 的CreateTime 设置为开服时间了.
// 	//gi.SrvStatus = int(smd.SrvStatus)
// 	//gi.GroupName = smd.GName
// 	//gi.GroupLoad = int(smd.Load) //DB没有此字段,gorm=-
// 	////gi.CreateTime = smd.CreatedAt.Unix()
// 	//if smd.EndRegTime != "" {
// 	//	endRegTime, _ := time.Parse(time.RFC3339, smd.EndRegTime)
// 	//	gi.EndRegTime = endRegTime.Unix()
// 	//}
// 	//gi.AreaID = 0
// 	//gi.IsRecommend = smd.IsRecommend
// 	//gi.IsNew = smd.IsNew
// 	return gi
// }

// func (this *LoginDBManager) GetGroupMd(groupId uint32) (ret *protoMsg.GroupMD) {
// 	util.UsingRead(&this.lkGroupList, func() {
// 		if v, ok := this.groupList[groupId]; ok {
// 			ret = v
// 		}
// 	})
// 	return
// }

// func (this *LoginDBManager) UpdateGroupSrvOpenTime(ret *protoMsg.GroupMD) {
// 	util.UsingWiter(&this.lkGroupList, func() {
// 		if v, ok := this.groupList[ret.GroupID]; ok {
// 			//v.SetSrvOpenTime(ret.GetSrvOpenTime())
// 			this.MysqlDB.Model(ret).UpdateColumn("srv_open_time", ret.SrvOpenTime)
// 			v.SrvOpenTime = ret.GetSrvOpenTime()
// 		}
// 	})
// 	return
// }

// // 更新服务器的新账号注册限制功能
// func (this *LoginDBManager) UpdateGroupEndRegTime(ret *protoMsg.GroupMD) {
// 	util.UsingWiter(&this.lkGroupList, func() {
// 		if v, ok := this.groupList[ret.GroupID]; ok {
// 			if ret.EndRegTime == "" {
// 				this.MysqlDB.Model(ret).UpdateColumn("end_reg_time", nil)
// 			} else {
// 				this.MysqlDB.Model(ret).UpdateColumn("end_reg_time", ret.EndRegTime)
// 			}
// 			v.SrvOpenTime = ret.GetSrvOpenTime()
// 		}
// 	})
// 	return
// }

// // GetUserGroupListAckByCache 通过openid获取全部服务器列表
// func (this *LoginDBManager) GetUserGroupListAckByCache() (ret *login.GetGroupListAck) {
// 	ret = new(login.GetGroupListAck)
// 	var gsrvli *login.GetGroupListAck
// 	now := time.Now()
// 	util.UsingRead(&this.lkGlobalSrvList, func() {
// 		gsrvli = this.GlobalSrvList
// 		ret.AreaList = make([]login.AreaInfo, len(gsrvli.AreaList))
// 		for i, areaInfo := range gsrvli.AreaList {
// 			ai := new(login.AreaInfo)
// 			ai.AreaID = areaInfo.AreaID
// 			ai.AreaName = areaInfo.AreaName
// 			ai.GroupList = make([]*login.GroupInfo, 0, len(areaInfo.GroupList))
// 			for _, group := range areaInfo.GroupList {
// 				if group.SrvOpenTime > now.Unix() { //过滤 开服时间在未来 过滤不给客户端发改服务器信息
// 					continue
// 				}
// 				group2 := group.Clone()
// 				if group2.SrvStatus == 5 {
// 					group2.GroupLoad = -1 //客户端根据这个值判断是 维护中
// 				}
// 				ai.GroupList = append(ai.GroupList, group2)
// 			}
// 			ret.AreaList[i] = *ai
// 		}
// 	})
// 	return
// }
// func (this *LoginDBManager) GMGetAreaAndGroupListAckByCache() (ret *login.GmGetAreaAndGroupListAck) {
// 	ret = new(login.GmGetAreaAndGroupListAck)
// 	util.UsingRead(&this.lkGlobalSrvList, func() {
// 		ret.AreaList = make([]login.AreaInfo, len(this.GlobalSrvList.AreaList))
// 		for i, areaInfo := range this.GlobalSrvList.AreaList {
// 			ai := new(login.AreaInfo)
// 			ai.AreaID = areaInfo.AreaID
// 			ai.AreaName = areaInfo.AreaName
// 			ret.AreaList[i] = *ai
// 		}
// 	})
// 	util.UsingRead(&this.lkGroupList, func() {
// 		for _, group := range this.groupList {
// 			gi := ToLoginGroupMsg(group)
// 			ret.GroupList = append(ret.GroupList, gi)
// 		}
// 	})
// 	sort.Slice(ret.GroupList, func(i, j int) bool {
// 		return ret.GroupList[i].GroupID < ret.GroupList[j].GroupID
// 	})
// 	return
// }

// // 根据账号信息 获得区服列表 (可能会根据渠道 或者 语言 筛选). (白名单 需要看到备服和 GM后台维护状态去除的 服务器列表)
// func (this *LoginDBManager) GetUserGroupListAckByUserInfo(userMd *protoMsg.UserMD) (ret *login.GetGroupListAck) {
// 	_ = this.GetUserGroupListAckByCache //NOTE 这个是没有用户过滤的原始版本

// 	rdUtil := dbservice.LoginPidUtil(userMd.UserID)
// 	device := rdUtil.GetDeviceInfo()
// 	isWhite := len(this.GetOneWhiteList(userMd.UserID, userMd.OpenID, userMd.Channel, device.GetDeviceId())) > 0

// 	//如果是白名单 解除限制: 1 可以看到备服;2 可以看到GM维护中的服务器<显示为正常>
// 	var gsrvli *login.GetGroupListAck
// 	now := time.Now()
// 	util.UsingRead(&this.lkGlobalSrvList, func() {
// 		gsrvli = &login.GetGroupListAck{}
// 		//所有用户都要筛选服务器列表, 白名单会筛选更多的服务器吧?????.
// 		for _, v := range this.GlobalSrvList.AreaList {
// 			areaGroup := login.AreaInfo{AreaID: v.AreaID, AreaName: v.AreaName, GroupList: nil}
// 			for _, group := range v.GroupList {
// 				group2 := group.Clone()
// 				isFutureSrv := group.SrvOpenTime > now.Unix()                          //备服  开服时间在未来
// 				isMaintenance := group.SrvStatus != int(protoMsg.SrvStatusEnum_Normal) //维护中 不可进入

// 				//维护中 且是白名单,会修改状态
// 				if isWhite && (isMaintenance || isFutureSrv) {
// 					group2.SrvStatus = 0 //修改
// 					areaGroup.GroupList = append(areaGroup.GroupList, group2)
// 				} else {
// 					if isFutureSrv { //过滤不给客户端发 备服
// 						continue
// 					}
// 					if isMaintenance {
// 						group2.GroupLoad = -1 //客户端根据这个值判断是 维护中
// 					}
// 					areaGroup.GroupList = append(areaGroup.GroupList, group2)
// 				}
// 			}
// 			gsrvli.AreaList = append(gsrvli.AreaList, areaGroup)
// 		}
// 	})
// 	return gsrvli
// }

// // 根据玩家信息查询白名单 白名单用户可以 1进入维护中的区服,2创角不受注册时间限制
// func (this *LoginDBManager) GetOneWhiteList(uid uint64, OpenId string, channelId string, deviceId string) (ret []*protoMsg.WhiteListMD) {
// 	util.UsingRead(&this.lkWhiteList, func() {
// 		for _, v := range this.whiteList {
// 			if uid != 0 && v.UID == uid {
// 				ret = append(ret, v)
// 			}
// 			if deviceId != "" && v.DeviceId == deviceId {
// 				ret = append(ret, v)
// 			}
// 			if OpenId != "" && channelId != "" && v.OpenId == OpenId && v.ChannelID == channelId {
// 				ret = append(ret, v)
// 			}
// 		}
// 	})
// 	if len(ret) > 0 {
// 		logger.Debugf(logger.LogKey_LoginFlow, "用户:%v,%v-%v,%v 是白名单用户", uid, OpenId, channelId, deviceId)
// 	}
// 	//queryDb := this.MysqlDB.Model(ret)
// 	//if uid != 0 {
// 	//	queryDb = queryDb.Or("uid=?", uid)
// 	//}
// 	//if deviceId != "" {
// 	//	queryDb = queryDb.Or("deviceId=?", deviceId)
// 	//}
// 	//if channelId != "" && OpenId != "" {
// 	//	queryDb = queryDb.Or("openId=? and channelId=?", OpenId, channelId)
// 	//} else {
// 	//	return nil
// 	//}
// 	//sql := queryDb.ToSQL(func(tx *gorm.DB) *gorm.DB {
// 	//	var ret2 []*protoMsg.WhiteListMD
// 	//	return tx.Find(&ret2)
// 	//})
// 	//logger.Info(sql)
// 	//queryDb.Find(&ret)

// 	return
// }

// func (this *LoginDBManager) QueryGetAllWhiteListMD() (whiteList []*protoMsg.WhiteListMD) {
// 	this.MysqlDB.Model(whiteList).Find(&whiteList)
// 	return
// }

// // 获得所有的白名单列表
// func (this *LoginDBManager) GetAllWhiteList() (ret []*protoMsg.WhiteListMD) {
// 	util.UsingRead(&this.lkWhiteList, func() {
// 		ret = make([]*protoMsg.WhiteListMD, len(this.whiteList))
// 		copy(ret, this.whiteList)
// 	})
// 	return
// }

// // 设置白名单 为玩家的信息
// func (this *LoginDBManager) SetOneWhiteList(wtype protoMsg.WhiteListTypeEnum, uid uint64, OpenId string, channelId string, deviceId string) (ret *protoMsg.WhiteListMD) {
// 	ret = &protoMsg.WhiteListMD{}
// 	ret.WType = wtype
// 	ret.UID = uid
// 	ret.OpenId = OpenId
// 	ret.ChannelID = channelId
// 	ret.DeviceId = deviceId

// 	queryDb := this.MysqlDB.Model(ret).Where("wtype=?", ret.WType)
// 	switch wtype {
// 	case protoMsg.WhiteListTypeEnum_PlayerUid:
// 		if db := queryDb.Where("uid=?", uid).Take(ret); db.Error == nil && ret.ID != 0 {
// 			return ret
// 		}
// 		db := this.MysqlDB.Model(ret).Create(ret)
// 		if db.Error != nil {
// 			logger.Error(db.Error)
// 			return nil
// 		}
// 	case protoMsg.WhiteListTypeEnum_OpenIdChannel:
// 		if db := queryDb.Where("openId=? and channelId=?", OpenId, channelId).Take(ret); db.Error == nil && ret.ID != 0 {
// 			return ret
// 		}
// 		db := this.MysqlDB.Model(ret).Create(ret)
// 		if db.Error != nil {
// 			logger.Error(db.Error)
// 			return nil
// 		}
// 	case protoMsg.WhiteListTypeEnum_DeviceId:
// 		if db := queryDb.Where("deviceId=?", deviceId).Take(ret); db.Error == nil && ret.ID != 0 {
// 			return ret
// 		}
// 		db := this.MysqlDB.Model(ret).Create(ret)
// 		if db.Error != nil {
// 			logger.Error(db.Error)
// 			return nil
// 		}
// 	default:
// 		logger.Error("Operation not impl!")
// 		return nil
// 	}

// 	this.lkWhiteList.Lock()
// 	defer this.lkWhiteList.Unlock()
// 	this.whiteList = this.QueryGetAllWhiteListMD()
// 	return ret
// }

// func JoinGroupSliceToString(GroupIDs []uint32) string {
// 	var GIDs string
// 	for k, v := range GroupIDs {
// 		GIDs += fmt.Sprintf("%v", v)
// 		if k != len(GroupIDs)-1 {
// 			GIDs += ","
// 		}
// 	}
// 	return GIDs
// }

// // 设置白名单 为玩家的信息
// func (this *LoginDBManager) SetMultiWhiteList(Array []*login.SetOneWhiteListGmReq) (datas []*protoMsg.WhiteListMD) {
// 	for _, v := range Array {
// 		ret := &protoMsg.WhiteListMD{}
// 		queryDb := this.MysqlDB.Model(ret)
// 		ret.WType = v.WType
// 		ret.UID = v.UID
// 		ret.OpenId = v.OpenId
// 		ret.ChannelID = v.ChannelID
// 		ret.DeviceId = v.DeviceId

// 		queryDb.Where(ret).Assign(ret).FirstOrCreate(ret)
// 		if queryDb.Error != nil {
// 			logger.Error(queryDb.Error)
// 			datas = append(datas, ret)
// 			continue
// 		}
// 		datas = append(datas, ret)
// 	}
// 	this.lkWhiteList.Lock()
// 	defer this.lkWhiteList.Unlock()
// 	this.whiteList = this.QueryGetAllWhiteListMD()
// 	return
// }

// func (this *LoginDBManager) DeleteWhiteList(ids []uint64) (affectedNum int64) {
// 	util.UsingWiter(&this.lkWhiteList, func() {
// 		for index, one := range this.whiteList {
// 			for _, keyId := range ids {
// 				if keyId == one.UID {
// 					//从slice中删除一个白名单
// 					this.whiteList = append(this.whiteList[:index], this.whiteList[index+1:]...)
// 					break
// 				}
// 			}
// 		}
// 		db := this.MysqlDB.Model(&protoMsg.WhiteListMD{}).Where("id in ?", ids).Delete(nil)
// 		affectedNum = db.RowsAffected
// 	})
// 	return
// }

// func (this *LoginDBManager) SetOneSrvMaintenance(groupId uint32, isMaintenance bool) (isset bool) {
// 	util.UsingWiter(&this.lkGroupList, func() {
// 		if v, ok := this.groupList[groupId]; ok {
// 			switch v.SrvStatus {
// 			case protoMsg.SrvStatusEnum_Normal:
// 				if isMaintenance {
// 					db := this.MysqlDB.Model(v).UpdateColumn("srv_status", protoMsg.SrvStatusEnum_Maintenance)
// 					if db.Error != nil {
// 						logger.Warn("Err:", db.Error)
// 						return
// 					}
// 					v.SrvStatus = protoMsg.SrvStatusEnum_Maintenance
// 					isset = true
// 					return
// 				} else {
// 					isset = true
// 					return
// 				}
// 			case protoMsg.SrvStatusEnum_Maintenance:
// 				if !isMaintenance {
// 					db := this.MysqlDB.Model(v).UpdateColumn("srv_status", protoMsg.SrvStatusEnum_Normal)
// 					if db.Error != nil {
// 						logger.Warn("Err:", db.Error)
// 						return
// 					}
// 					v.SrvStatus = protoMsg.SrvStatusEnum_Normal
// 					isset = true
// 					return
// 				} else {
// 					isset = true
// 					return
// 				}
// 			}

// 		}
// 	})
// 	if isset {
// 		util.UsingRead(&this.lkGroupList, func() {
// 			this.MakeCacheAllSrvList(this.groupList)
// 		})
// 	}
// 	return
// }
// func BoolToInt(n bool) int {
// 	if n {
// 		return 1
// 	}
// 	return 0
// }

// func (this *LoginDBManager) SetOneSrvRecommendOrNewTag(groupId uint32, op int, val bool) (isset bool) {
// 	util.UsingWiter(&this.lkGroupList, func() {
// 		if v, ok := this.groupList[groupId]; ok {
// 			if op == 1 {
// 				db := this.MysqlDB.Model(v).UpdateColumn("is_recommend", BoolToInt(val))
// 				if db.Error != nil {
// 					logger.Warn("Err:", db.Error)
// 					return
// 				}
// 				v.IsRecommend = val
// 				isset = true
// 			} else if op == 2 {
// 				db := this.MysqlDB.Model(v).UpdateColumn("is_new", BoolToInt(val))
// 				if db.Error != nil {
// 					logger.Warn("Err:", db.Error)
// 					return
// 				}
// 				v.IsNew = val
// 				isset = true

// 			} else {
// 				return
// 			}

// 		}
// 	})
// 	if isset {
// 		util.UsingRead(&this.lkGroupList, func() {
// 			this.MakeCacheAllSrvList(this.groupList)
// 		})
// 	}
// 	return
// }

// func (_ *LoginDBManager) compareAndUpdateGroupMDByGroupBase(groupMd *protoMsg.GroupMD, base *login.GroupBaseInfo) map[string]interface{} {
// 	if groupMd.GroupID != base.GroupID {
// 		return nil
// 	}

// 	var columns = map[string]interface{}{}
// 	if groupMd.GName != base.GroupName {
// 		//query.UpdateColumns("gname", base.GroupName)
// 		columns["gname"] = base.GroupName
// 		groupMd.GName = base.GroupName
// 	}
// 	if groupMd.AreaID != base.AreaID {
// 		//query.UpdateColumn("aid", base.AreaID)
// 		columns["aid"] = base.AreaID
// 		groupMd.AreaID = base.AreaID
// 	}
// 	if base.SrvStatus != nil && int(groupMd.SrvStatus) != *base.SrvStatus {
// 		//query.UpdateColumn("srv_status", *base.SrvStatus)
// 		columns["srv_status"] = *base.SrvStatus
// 		groupMd.SrvStatus = protoMsg.SrvStatusEnum(*base.SrvStatus)
// 	}
// 	if base.SrvOpenTime != nil && int64(groupMd.SrvOpenTime) != *base.SrvOpenTime {
// 		columns["srv_open_time"] = *base.SrvOpenTime
// 		groupMd.SrvOpenTime = *base.SrvOpenTime
// 	}
// 	if base.IsRecommend != nil && (groupMd.IsRecommend) != *base.IsRecommend {
// 		columns["is_recommend"] = *base.IsRecommend
// 		groupMd.IsRecommend = *base.IsRecommend
// 	}
// 	if base.IsNew != nil && (groupMd.IsNew) != *base.IsNew {
// 		columns["is_new"] = *base.IsNew
// 		groupMd.IsNew = *base.IsNew
// 	}
// 	if base.EndRegTime != nil && (groupMd.EndRegTime) != gcommon.ToJsonString(*base.EndRegTime) {
// 		columns["end_reg_time"] = *base.EndRegTime
// 		groupMd.EndRegTime = gcommon.ToJsonString(*base.EndRegTime)
// 	}

// 	return columns
// }
